package distributed

import (
	"fmt"
	"github.com/gocolly/colly"
	"regexp"
	"time"
)

var visited = map[string]bool{}

func Crawler() {
	// Instantiate default collector
	c := colly.NewCollector(
		colly.AllowedDomains("www.abcdefg.com"),
		colly.MaxDepth(1),
	)

	// 我们认为匹配该模式的是该网站的详情页
	detailRegex, _ := regexp.Compile(`/go/go\?p=\d+$`)
	// 匹配下面模式的是该网站的列表页
	listRegex, _ := regexp.Compile(`/t/\d+#\w+`)

	// 所有a标签，上设置回调函数
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		link := e.Attr("href")

		// 已访问过的详情页或列表页，跳过
		if visited[link] && (detailRegex.Match([]byte(link)) || listRegex.Match([]byte(link))) {
			return
		}

		// 既不是列表页，也不是详情页
		// 那么不是我们关心的内容，要跳过
		if !detailRegex.Match([]byte(link)) && !listRegex.Match([]byte(link)) {
			println("not match", link)
			return
		}

		// 因为大多数网站有反爬虫策略
		// 所以爬虫逻辑中应该有 sleep 逻辑以避免被封杀
		time.Sleep(time.Second)
		println("match", link)

		visited[link] = true

		time.Sleep(time.Millisecond * 2)
		c.Visit(e.Request.AbsoluteURL(link))
	})

	err := c.Visit("https://www.abcdefg.com/go/go")
	if err != nil {
		fmt.Println(err)
	}
}

//var domain2Collector = map[string]*colly.Collector{}
//var nc *nats.Conn
//var maxDepth = 10
//var natsURL = "nats://localhost:4222"
//
//func factory(urlStr string) *colly.Collector {
//	u, _ := url.Parse(urlStr)
//	return domain2Collector[u.Host]
//}
//
//func initABCDECollector() *colly.Collector {
//	c := colly.NewCollector(
//		colly.AllowedDomains("www.abcdefg.com"),
//		colly.MaxDepth(maxDepth),
//	)
//
//	c.OnResponse(func(resp *colly.Response) {
//		// 做一些爬完之后的善后工作
//		// 比如页面已爬完的确认存进 MySQL
//	})
//
//	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
//		// 基本的反爬虫策略
//		link := e.Attr("href")
//		time.Sleep(time.Second * 2)
//
//		// 正则 match 列表页的话，就 visit
//		if listRegex.Match([]byte(link)) {
//			c.Visit(e.Request.AbsoluteURL(link))
//		}
//		// 正则 match 落地页的话，就发消息队列
//		if detailRegex.Match([]byte(link)) {
//			err = nc.Publish("tasks", []byte(link))
//			nc.Flush()
//		}
//	})
//	return c
//}
//
//func initHIJKLCollector() *colly.Collector {
//	c := colly.NewCollector(
//		colly.AllowedDomains("www.hijklmn.com"),
//		colly.MaxDepth(maxDepth),
//	)
//
//	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
//	})
//
//	return c
//}
//
//func CrawlerInit() {
//	domain2Collector["www.abcdefg.com"] = initV2exCollector()
//	domain2Collector["www.hijklmn.com"] = initV2fxCollector()
//
//	var err error
//	nc, err = nats.Connect(natsURL)
//	if err != nil {
//		os.Exit(1)
//	}
//}
//
//func DistributedCrawler() {
//	CrawlerInit()
//	urls := []string{"https://www.abcdefg.com", "https://www.hijklmn.com"}
//	for _, url := range urls {
//		instance := factory(url)
//		instance.Visit(url)
//	}
//}
//
////var domain2Collector = map[string]*colly.Collector{}
////var nc *nats.Conn
////var maxDepth = 10
////var natsURL = "nats://localhost:4222"
//
//func factory(urlStr string) *colly.Collector {
//	u, _ := url.Parse(urlStr)
//	return domain2Collector[u.Host]
//}
//
//func initV2exCollector() *colly.Collector {
//	c := colly.NewCollector(
//		colly.AllowedDomains("www.abcdefg.com"),
//		colly.MaxDepth(maxDepth),
//	)
//	return c
//}
//
//func initV2fxCollector() *colly.Collector {
//	c := colly.NewCollector(
//		colly.AllowedDomains("www.hijklmn.com"),
//		colly.MaxDepth(maxDepth),
//	)
//	return c
//}
//
//func init() {
//	domain2Collector["www.abcdefg.com"] = initABCDECollector()
//	domain2Collector["www.hijklmn.com"] = initHIJKLCollector()
//
//	var err error
//	nc, err = nats.Connect(natsURL)
//	if err != nil {os.Exit(1)}
//}
//
//func startConsumer() {
//	nc, err := nats.Connect(nats.DefaultURL)
//	if err != nil {return}
//
//	sub, err := nc.QueueSubscribeSync("tasks", "workers")
//	if err != nil {return}
//
//	var msg *nats.Msg
//	for {
//		msg, err = sub.NextMsg(time.Hour * 10000)
//		if err != nil {break}
//
//		urlStr := string(msg.Data)
//		ins := factory(urlStr)
//		// 因为最下游拿到的一定是对应网站的落地页
//		// 所以不用进行多余的判断了，直接爬内容即可
//		ins.Visit(urlStr)
//		// 防止被封杀
//		time.Sleep(time.Second)
//	}
//}
